;==================================================================
; THUNDER FORCE 3 Ohtsuka COMPRESSION
; AUTHOR : oostyx (at) gmail (dot) com
; (maybe some little errors in conditions tests...)
; Thanks to doc mefisto, who helps me to find this compression
; method.
;------------------------------------------------------------------
; ROM ADRESS : 	0x56CE (OhtsukaLoad1)
;		0x5734 (OhtsukaLoad2)
;		0x57A0 (OhtsukaLoad3?)
;		0x5842 (OhtsukaLoadBoss)
;
; There a lot of differences between these subroutines, but
; all of them uncompress some data using the Ohtsuka format.
;------------------------------------------------------------------
; Compression method : Run Length Encoding
; Usage : small art blocks, which must be loaded quickly
; Programer's name for the method : Ohtsuka, because Iwanaga was 
;				the first discovered cpr method
; 				(2nd programer's name on game credits)
;------------------------------------------------------------------

;======================================================
; OhtsukaLoad2 Uncompression subroutine : entry point A				
;======================================================
;---------------------------------------------------------
// parameters with this entry point : 
	// a0 = art ptr table
	// d0 = number of art bank to decode and load to VRAM
	// a1 = VRAM adress for data transfer
;---------------------------------------------------------

OstukaLoad2_A:

	do <<= 2;
	d0 = a0[d0];
	a0 += d0;
	(goto OhtsukaLoad2_B;)
	
;=======================================================
; OhtsukaLoad2 Uncompression subroutine : entry point B
;=======================================================
;------------------------------------------------------
; parameters with this entry point :
; a0 : direct pointer to art bank
;------------------------------------------------------
; Register USAGE
;------------------------------------------------------
; d4				only used to fix the cmd nibble
; a0 = ArtBank			a pointer to the cpr data
; d6 = CprNbRepeats		a long
; d7 = CprUnits			a long : a counter to know when
					 the uncpr is finished
; d2 = CprNibble		a nibble : uncpr data
; d1 = CprCmd			a nibble : RLE command
; d0 = UncprBuffer		a long
; d3 = Counter			a byte : to know when the uncprbuffer 
					is ready to be written in VRAM
; a1 = VRAM				a pointer to VRAM DATA (C00004)
;------------------------------------------------------

OhtsukaLoad2_B:

	CprUnits = ArtBank.popLong();
	CprUnits >>= 2; 			
	
	VDPVRAMAccess();		// to request VRAM access
	
	Counter = 8;
		
	while (1)			// endless loop, return is done by subOhtsukaLoad2
	{
			CprCmd = ArtBank.popByte();
			CprNibble = CprCmd;
			CprNibble >>= 4;				// taking the 4 upper bits of the cpr data
			CprNbRepeats = 0;				// init the CprNbRepeats
			CprCmd &= 0b0000000000001111;			//fixing the nibble	
			
			switch (CprCmd)
			{
				case 0x0D:
					CprNbRepeats = ArtBank.popByte();
					break;

				case 0x0E:
					CprNbRepeats = ArtBank.popWord();
					break;

				case 0x0F:
					CprNbRepeats = ArtBank.popWord();
					CprNbRepeats += 0x10000;
					break;

				default:
					CprNbRepeats = CprCmd;
			}

			do
			{
				subOhtsukaLoad2();
			}
			while (--CprNbRepeats > 0);
	}

;=====================================================
; SUBROUTINE subOhtsukaLoad2
;=====================================================

subOhtsukaLoad2:

		UncprBuffer <<= 4;				// pushing a nibble
		UncprBuffer |= CprNibble;
		
		if (--Counter == 0)
		{
			VRAM.pushLong(d0);			// writing UncprBuffer to VRAM			
			Counter = 8;				// Counter is set to 8 because UncprBuffer is 32 bits long
								// so 8 CprNibbles (4 bits) must be written
			
			if (--CprUnits == 0)
			{
				// using this asm :
				//	addq.l  #4,sp		// set stack pointer on the next return adress
				//	rts			// performs a return (sp popped, with the adress 
								// of the OhtsukaLoad2 caller)
				
				return to OhtsukaLoad2 caller;
			}
		}
		
		return;
	
